import cv2
# 从handprocess文件中导入HandDetector类
from hand_process import HandDetector
 

# 打开摄像头
cap = cv2.VideoCapture(0)

# 定义一个全局变量来存储安全区域
safety_zone = None
drawing = False  # 标志是否正在绘制安全区域
 
 
# 定义鼠标事件函数，用于选择安全区域
def draw_rectangle(event, x, y, flags, param):
    global safety_zone, drawing
    if event == cv2.EVENT_LBUTTONDOWN:  # 开始绘制
        drawing = True
        safety_zone = [(x, y)]  # 存储矩形的起始点
    elif event == cv2.EVENT_MOUSEMOVE and drawing:  # 鼠标移动，实时更新矩形
        img_copy = frame.copy()
        cv2.rectangle(img_copy, safety_zone[0], (x, y), (255, 0, 0), 2)
        cv2.imshow('Draw Safety Zone', img_copy)
    elif event == cv2.EVENT_LBUTTONUP:  # 完成绘制
        drawing = False
        safety_zone.append((x, y))  # 存储矩形的结束点
 
 
# 创建窗口并绑定鼠标事件，用于绘制安全区域
cv2.namedWindow('Draw Safety Zone')
cv2.setMouseCallback('Draw Safety Zone', draw_rectangle)
 
# 获取用户手动框选的安全区域
while True:
    ret, frame = cap.read()
    if not ret:
        break
    cv2.imshow('Draw Safety Zone', frame)
 
    if safety_zone and len(safety_zone) == 2:
        break  # 已绘制完成
 
    if cv2.waitKey(1) & 0xFF == ord('q'):  # 按 'q' 键退出
        break
 
cv2.destroyWindow('Draw Safety Zone')
# 创建一个手势识别对象
detector = HandDetector()
# 6张手的图片，分别代表0～5
finger_img_list = [
    'd:/workspaces/OpenPoseStudy/mediapipeModel/images/0.png',
    'd:/workspaces/OpenPoseStudy/mediapipeModel/images/1.png',
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/2.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/3.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/4.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/5.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/6.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/7.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/8.png",
    "d:/workspaces/OpenPoseStudy/mediapipeModel/images/9.png"
]
# 创建一个列表来存放表示0~5的图片
finger_list = []
# 遍历finger_img_list列表
for gesture in finger_img_list:
    # 用cv2.imread()函数把图片依次取出来
    i = cv2.imread(gesture)
    # 把取出来的图片存到finger_list列表中
    finger_list.append(i)
# 指尖地表值，分别代表大拇指、食指、中指、无名指和小指的指尖
tip_ids = [4, 8, 12, 16, 20]
object_color_range = ((0, 0, 100), (180, 30, 50))  # 黑色物体范围
color = (0, 255, 0)  # BGR格式的颜色，例如绿色
thickness = 2  # 线宽
 # 创建窗口并设置为可调整大小
# cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
# cv2.setWindowProperty('Image', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

while True:
    # 不断取出从摄像头捕获的视频图像，返回两个数，一个是是否成功取出，另一个是捕获到的图像
    success, img = cap.read()
    # 如果成功取出
    if success:
        # 先翻转图像，因为从摄像头取出图像是翻转，我们需要镜像的
        img = cv2.flip(img, 1)
        # 调用HandDetector类中的find_hands成员方法，识别出img中的手，并画出21个手势地标
        # 绘制矩形
        cv2.rectangle(img, safety_zone[0], safety_zone[1], color, thickness)
        #获取矩形内的栈帧
        roi_gray = img[safety_zone[0][1]:safety_zone[1][1], safety_zone[0][0]:safety_zone[1][0]]
        roi_gray = detector.find_hands(roi_gray, draw=True)
        # 调用find_positions成员方法，计算出21个手势地标的索引值和坐标
        sun = detector.find_positions(roi_gray)
  
        # # 如果sun中有元素
        if len(sun) > 0:
            # 先定义一个空列表，用户存放0和1,0表示手指闭合，1表示手指张开
            fingers = []
            # 遍历5根手指的指尖
            for tid in tip_ids:
                # 取出指尖的x坐标和y坐标
                x, y = sun[tid][1], sun[tid][2]
                # 在指尖上画一个圆
                cv2.circle(roi_gray, (x, y), 10, (0, 0, 255), cv2.FILLED)
                # 如果是大拇指
                if tid == 4:
                    # 如果大拇指指尖的x位置大于第二个关节的第二个位置，则认为大拇指打开
                    if sun[tid][1] > sun[tid - 1][1]:
                        # 给fingers列表添加一个1元素，表示一个手指张开，识别到的数字就加一
                        fingers.append(1)
                    else:
                        # 给fingers列表添加一个0元素，表示一个手指闭合，识别到的数字就不变
                        fingers.append(0)
                # 如果是其他手指
                else:
                    # 如果这些手指的指尖的y位置大于第二关节的位置，则认为这个手指打开，否则认为这个手指关闭
                    if sun[tid][2] < sun[tid - 2][2]:
                        fingers.append(1)
                    else:
                        fingers.append(0)
            # 判断有几个手指打开
            cnt = fingers.count(1)
            # 找出对应的数字图片，并显示
            finger_img = finger_list[cnt]
            # 计算所要添加图片的长和宽
            w, h, c = finger_img.shape
            # 在img图像的左上角添加图片
            img[0:w, 0:h] = finger_img
            # 在对应img的对应坐标位置添加一个矩形（绿色），并填充该矩形
            cv2.rectangle(img, (0, 200), (100, 300), (0, 255, 0), cv2.FILLED)
            # 在矩形中添加识别到的数字（红色）
            cv2.putText(img, str(cnt), (0, 300), cv2.FONT_HERSHEY_DUPLEX, 5, (0, 0, 255), 2)
        # 将img显示在以Image命名的窗口
        cv2.imshow('Image', img)
    # 等待按下一个键，并将该键的ASCII码值赋值给变量k
    k = cv2.waitKey(1)
    # 如果按下的是q，则退出循环
    if k == ord('q'):
        break
# 释放VideoCapture对象，防止程序占用摄像头，以释放资源
cap.release()
# 关闭所有由OpenCV创建的窗口
cv2.destroyAllWindows()